/*
 * DemoEntity.h
 *
 * @author Andrew Dyer
 */

class DemoEntity {
  btBoxShape* shape_;
  btTransform* transform_;
    
  btDefaultMotionState* motion_state_;
  btRigidBody* rigid_body_;

public:
  DemoEntity() {}

  void init(btScalar mass, const btVector3 &inertia, const btVector3 &pos, const btVector3 &size) {
    motion_state_ = new btDefaultMotionState(btTransform(btMatrix3x3::getIdentity(), pos));
    shape_ = new btBoxShape(size);
    rigid_body_ = new btRigidBody(mass, motion_state_, shape_, inertia);
    rigid_body_->setFriction(1.0f);
  }

  btRigidBody* getRigidBody() {
    return rigid_body_;
  }

  void draw(shader &shader, mat4 &modelToProjection, vec4 color) {
    float xhe = shape_->getHalfExtentsWithMargin().getX();
    float yhe = shape_->getHalfExtentsWithMargin().getY();
    float zhe = shape_->getHalfExtentsWithMargin().getZ();

    btTransform wt;
    rigid_body_->getMotionState()->getWorldTransform(wt);
	  btVector3 position = wt.getOrigin();
    btQuaternion rotation = wt.getRotation();


    GLfloat vertices[3 * 8] = {
      -1,  1,  1,
      -1, -1,  1,
       1,  1,  1,
       1, -1,  1,
       1,  1, -1,
       1, -1, -1,
      -1,  1, -1,
      -1, -1, -1
    };

    for (int i = 0; i != 8; ++i) {
      int index = i * 3;

      // Scale
      vertices[  index  ] = vertices[  index  ] * xhe;
      vertices[index + 1] = vertices[index + 1] * yhe;
      vertices[index + 2] = vertices[index + 2] * zhe;

      // Rotate
      quat q(rotation.getX(), rotation.getY(), rotation.getZ(), rotation.getW());
      vec4 rot = q.rotate(vec4(vertices[index], vertices[index + 1], vertices[index + 2], 0));

      vertices[  index  ] = rot[0];
      vertices[index + 1] = rot[1];
      vertices[index + 2] = rot[2];

      // Translate
      vertices[  index  ] = vertices[  index  ] + position.getX();
      vertices[index + 1] = vertices[index + 1] + position.getY();
      vertices[index + 2] = vertices[index + 2] + position.getZ();
    }


    GLubyte indices [3 * 12] = {
      0, 1, 2,   1, 3, 2,
      2, 3, 4,   3, 5, 4,
      4, 5, 6,   5, 7, 6,
      6, 7, 0,   0, 7, 1,
      0, 4, 6,   0, 2, 4,
      1, 7, 3,   3, 7, 5
    };


    
    if (rigid_body_->wantsSleeping()) {
      shader.render(modelToProjection, vec4(0, 0, 0, 1));
    }
    else if(rigid_body_->isActive()) {
      shader.render(modelToProjection, vec4(0.5, 0.3, 0.1f, 1));
    } else {
      shader.render(modelToProjection, vec4(0, 0, 0, 1));
    }



    GLubyte lineIndices [2 * 12] = {
      0, 2,  2, 4,  4, 6,  6, 0,
      1, 3,  3, 5,  5, 7,  7, 1,
      0, 1,  2, 3,  4, 5,  6, 7
    };

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
    glEnableVertexAttribArray(0);

    glDrawElements(GL_LINES, sizeof(lineIndices) / sizeof(GLubyte), GL_UNSIGNED_BYTE, lineIndices);

    
    
    shader.render(modelToProjection, color);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
    glEnableVertexAttribArray(0);

    glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(GLubyte), GL_UNSIGNED_BYTE, indices);


    


  }

  void cleanup() {
    delete rigid_body_;
    delete shape_;
    delete motion_state_;
  }
};
